package stz.flash.main;

import net.rim.device.api.system.Application;
import net.rim.device.api.system.Characters;
import net.rim.device.api.system.Display;
import net.rim.device.api.ui.Color;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.Font;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.Keypad;
import net.rim.device.api.ui.Manager;
import net.rim.device.api.ui.component.LabelField;
import net.rim.device.api.ui.container.MainScreen;
import net.rim.device.api.ui.container.VerticalFieldManager;
import net.rim.device.api.ui.decor.BackgroundFactory;
import stz.flash.Info;
import stz.flash.main.flashlight.field.BatteryManager;
import stz.flash.main.flashlight.field.TimePanel;
import stz.flash.main.flashlight.model.Flashlight;
import stz.flash.main.state.KeyOperator;
import blackberry.util.DjFont;

/**
 * OS6의 경우에 Video가 화면에 모두 보여져만이 Flash가 켜지므로 
 * VideoField를 고정시키기 위해 Manager를 한층 더 만듬
 * 
 * @param afterDelHoldManager
 * 	Pearl에서 SpeakerPhone 키를 눌러서 Hold를 종료시킬때 키를 계속 누르고 있으면
 * 	KeyRepeat 이 곧바로 작동되어 다시 Hold가 나타나게 된다.
 * 	이 부자연스러운 상황을 해결하기위한 변수이다.
 * 
 */
public class ManagerOfManager extends Manager {
	
	private static MainManager mainManager = MainManager.getIns();
	private static Field videoManager = Flashlight.getVideoManager();
	private static TitleManager titleManager = TitleManager.getIns();
	
	private static TimePanel timePanel = new TimePanel();
	private static BatteryManager battery = new BatteryManager();
	private static BulbField bulbField = BulbField.getIns();
	private static TimerField timerField = new TimerField();
	
	private static HoldManager holdManager = new HoldManager();
	
	private static final int DISPLAY_TIME_OF_HOTKEY_ADVICE = 4000;
	private static HotkeyAdviceManager hotkeyAdviceManager = new HotkeyAdviceManager(timerField);
	private static Thread hotkeyAdviceThread;
	
	private static boolean displayedHoldManager;
	
	private static VerticalFieldManager testConsol = new VerticalFieldManager() {
		protected void sublayout(int maxWidth, int maxHeight) {
			super.sublayout(maxWidth, maxHeight);
			setExtent(getPreferredWidth(), getPreferredWidth());
		};
	};
	
	public ManagerOfManager() {
		super(0);
		
		KeyOperator.setManagerOfManager(this);
		
		add(mainManager);
		
		add(titleManager);
	
		add(testConsol);//test
		
		add(timePanel);
		
		add(battery);
		
		add(bulbField);
		
		add(timerField);

		add(videoManager);
		
	}
	
	public static void insertConsol(String str){
		testConsol.insert(new LabelField("" + str), 0);
	}
	
	/*
	 *  nextFocus(int, int)는 Manager에서 사용되는걸로 추정된다.
	 * 
	 * direction
	 * 1 = 오른쪽, 밑쪽 / -1 = 윗쪽, 왼쪽
	 * 
	 * axis
	 * 트랙패드는 axis값이 1(AXIS_HORIZONTAL), 2(AXIS_VERTICAL)로 나오고
	 * 트랙휠?(마우스휠)은 0(AXIS_SEQUENTIAL)으로 나온다.
	 * 
	 * return
	 * 다음 포커스의 index값을 나타낸다.(이동값이 아님)
	 * 
	 * super.nextFocus(int, int)
	 * Manager에서 빠저나올때는 -1을 반환한다.
	 */
	protected int nextFocus(int direction, int axis) {
		
		if (getFieldWithFocusIndex() == titleManager.getIndex()) {
			
			if (direction == 1 && (axis == AXIS_VERTICAL || axis == AXIS_SEQUENTIAL))
				return mainManager.getIndex();
			
			return titleManager.getIndex();

			
		} else if (getFieldWithFocusIndex() == mainManager.getIndex()) {
			
			if (direction == -1 && (axis == AXIS_VERTICAL || axis == AXIS_SEQUENTIAL))
				return titleManager.getIndex();
			
			return mainManager.getIndex();
		}
		
		return super.nextFocus(direction, axis);
	}
	
	
	public static boolean isDisplayedHoldManager(){
		return displayedHoldManager; 
	}
	
	public void toggleHoldManager(){
		
		if (holdManager.getIndex() == -1) {
		
			add(holdManager);
			displayedHoldManager = true;
		
		} else  {
			delete(holdManager);
			displayedHoldManager = false;
		}
	}
	
	
	public void displayHotkeyAdvice(){
		if (ManagerOfManager.hotkeyAdviceManager.getIndex() != -1) {
			hotkeyAdviceThread.interrupt();
			runHotkeyAdviceThread();
			return;
		}
		
		add(ManagerOfManager.hotkeyAdviceManager);
		TitleManager.getIns().addCLabel();
		runHotkeyAdviceThread();
	}
	private void runHotkeyAdviceThread() {
		
		hotkeyAdviceThread = new Thread() {
			public void run() {
				try {
					
					Thread.sleep(DISPLAY_TIME_OF_HOTKEY_ADVICE);
				
					synchronized (Application.getEventLock()) {
						delete(ManagerOfManager.hotkeyAdviceManager);
						TitleManager.getIns().delCLabel();
					}
					
				} catch (InterruptedException e) {
				}
			}
		};
		hotkeyAdviceThread.start();
	}

	
	protected boolean keyDown(int keycode, int time) {
		
		int key = Keypad.key(keycode);
		
		//홀드 상태일때 key를 걸러내어 MonkeyFlashController에 도달하지 못하게한다.
		//단 R키, Lock키, SpeakerPhone, VOLUME_UP, VOLUME_DOWN키는 그냥 통과시킨다. 
		if (holdStateIgnoreKey(key)) {
			return true;
		}
		
		if (key == Keypad.KEY_MENU)
			return false;
		
		KeyOperator.analyzeLocalKey(key);
		
		return true;//true를 반환하면 글로벌키가 중복되는걸 막을 수 있다.
	}
	private boolean holdStateIgnoreKey(int key) {
		return displayedHoldManager 
				&& (key != KeyOperator.RESET_TIMER_FRONT_KEY
				&& key != Characters.LATIN_CAPITAL_LETTER_A
				&& key != Characters.LATIN_CAPITAL_LETTER_Q
					&& key != Keypad.KEY_LOCK
					&& key != Keypad.KEY_SPEAKERPHONE
					&& key != Keypad.KEY_VOLUME_UP
					&& key != Keypad.KEY_VOLUME_DOWN);
	}
	
	protected boolean keyUp(int keycode, int time) {
		
		if ((Keypad.key(keycode) == Keypad.KEY_LOCK))
			return true;

		if (displayedHoldManager) {
			return true;
		}
		
		return super.keyUp(keycode, time);
	}
	
	protected boolean keyRepeat(int keycode, int time) {
		return true;
	}
	
	protected boolean navigationClick(int status, int time) {
		if (displayedHoldManager)
			return true;
		return super.navigationClick(status, time);
	}
	protected boolean navigationMovement(int dx, int dy, int status, int time) {
		if (displayedHoldManager)
			return true;
		return super.navigationMovement(dx, dy, status, time);
	}
	protected boolean navigationUnclick(int status, int time) {
		if (displayedHoldManager)
			return true;
		return super.navigationUnclick(status, time);
	}
	//navigation을 막으면 trackwheel도 자동으로 막히지만 찝찝해서 막아둠
	protected boolean trackwheelRoll(int arg0, int arg1, int arg2) {
		if (displayedHoldManager)
			return true;		
		return super.trackwheelRoll(arg0, arg1, arg2);
	}
	protected boolean trackwheelClick(int status, int time) {
		if (displayedHoldManager)
			return true;
		return super.trackwheelClick(status, time);
	}
	protected boolean trackwheelUnclick(int status, int time) {
		if (displayedHoldManager)
			return true;	
		return super.trackwheelUnclick(status, time);
	}
	
	
	public void sublayout(int width, int height) {
		setExtent(Display.getWidth(), Display.getHeight());
		
		setPositionChild(mainManager, AniEffect.getInt(), 0);
		layoutChild(mainManager, 
				mainManager.getPreferredWidth(), 
				mainManager.getPreferredHeight());

		
		setPositionChild(titleManager, 0, 0);
		layoutChild(titleManager, 
				titleManager.getPreferredWidth(), 
				titleManager.getPreferredHeight());
		
		
		setPositionChild(timePanel, 
				Info.PX_OF_1MM, 
				titleManager.getPreferredHeight());
		layoutChild(timePanel, 
				titleManager.getPreferredWidth(), 
				titleManager.getPreferredHeight());
		
		setPositionChild(battery, 
				timePanel.getLeft(), 
				timePanel.getTop() + timePanel.getPreferredHeight());
		layoutChild(battery, 
				battery.getPreferredWidth(), 
				battery.getPreferredHeight());
		

		
		setPositionChild(bulbField, 
				ImageXY.BULB[0], 
				ImageXY.BULB[1]);
		layoutChild(bulbField, 
				bulbField.getPreferredWidth(), 
				bulbField.getPreferredHeight());
		
		setPositionChild(timerField, 
				Info.PX_OF_1MM, 
				Display.getHeight() - timerField.getPreferredHeight());
		layoutChild(timerField, 
				timerField.getPreferredWidth(), 
				timerField.getPreferredHeight());
		

		
		if (videoManager.getIndex() != -1) {
			setPositionChild(videoManager, 0, 0);
			layoutChild(videoManager, 
					Display.getWidth(), 
					Display.getHeight());;
		}
		
		
		if (holdManager.getIndex() != -1) {
			setPositionChild(holdManager, 0, 0);
			layoutChild(holdManager, 
					Display.getWidth(), 
					Display.getHeight());;
		}
		
		
		if (ManagerOfManager.hotkeyAdviceManager.getIndex() != -1) {
			setPositionChild(ManagerOfManager.hotkeyAdviceManager, AniEffect.getInt(), 0);
			layoutChild(ManagerOfManager.hotkeyAdviceManager, 
					ManagerOfManager.hotkeyAdviceManager.getPreferredWidth(), 
					ManagerOfManager.hotkeyAdviceManager.getPreferredHeight());;
		}
		
		setPositionChild(testConsol, 0, battery.getTop() + battery.getPreferredHeight());
		layoutChild(testConsol, 
				testConsol.getPreferredWidth(), 
				testConsol.getPreferredHeight());;
	}
}



class HoldManager extends Manager {

	private static final String STRING_HOLD = "HOLD";
	private static final String STRING_HELP_MESSAGE = "홀드기능을 끄려면 잠금버튼을 다시한번 눌러주세요.";
	private static final int ADVANCE_HOLD = Display.getWidth() / 3;
	private static final int ADVANCE_HELP_MESSAGE = Display.getWidth() * 9 / 10;
	
	private static int holdFontHeight;
	private static int helpMessageFontHeight;
	
	private static HoldLabel holdField= new HoldLabel(STRING_HOLD);
	private static HoldLabel helpMessageField = new HoldLabel(STRING_HELP_MESSAGE);
	
	public HoldManager(){
		super(0);
		holdFontHeight = DjFont.getFontHeight(
				STRING_HOLD,
				ADVANCE_HOLD,
				getFont());
		helpMessageFontHeight = DjFont.getFontHeight(
				STRING_HELP_MESSAGE,
				ADVANCE_HELP_MESSAGE, 
				getFont());
		setFontSize();
		
		setBackground(BackgroundFactory.createSolidTransparentBackground(Color.BLACK, 50));
		add(holdField);
		add(helpMessageField);
	}
	
	private void setFontSize() {
		holdField.setFont(getFont().derive(Font.BOLD, holdFontHeight));
		helpMessageField.setFont(getFont().derive(Font.PLAIN, helpMessageFontHeight));
	}

	protected void sublayout(int arg0, int arg1) {
		setExtent(Display.getWidth(), Display.getHeight());

		setPositionChild(holdField, 
				(Display.getWidth() - holdField.getPreferredWidth()) >> 1,
				(Display.getHeight() - holdField.getPreferredHeight()) >> 1);
		layoutChild(holdField, holdField.getPreferredWidth(), holdField.getPreferredHeight());

		setPositionChild(helpMessageField, 
				(Display.getWidth() - helpMessageField.getPreferredWidth()) >> 1,
				holdField.getTop() + holdField.getPreferredHeight());
		layoutChild(helpMessageField, helpMessageField.getPreferredWidth(), holdField.getPreferredHeight());
	}
	
	static class HoldLabel extends LabelField {

		public HoldLabel(Object label) {
			super(label);
		}
		
		protected void paint(Graphics g) {
			g.setColor(Color.WHITE);
			super.paint(g);
		}
	}
}